package com.xjgzinfo.usdp.web.rest;

import cn.hutool.core.bean.BeanUtil;
import com.xjgzinfo.usdp.constant.AuthConstant;
import com.xjgzinfo.usdp.core.domain.PageWapper;
import com.xjgzinfo.usdp.core.domain.ResponsePage;
import com.xjgzinfo.usdp.core.domain.ResponseResult;
import com.xjgzinfo.usdp.jpa.service.filter.LongFilter;
import com.xjgzinfo.usdp.security.SecurityUtils;
import com.xjgzinfo.usdp.service.*;
import com.xjgzinfo.usdp.service.dto.*;
import com.xjgzinfo.usdp.service.vo.BladeVisualVO;
import com.xjgzinfo.usdp.web.rest.utils.BeanUtilsHepler;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.xjgzinfo.usdp.constant.AvueConstant.IMG_DIRS;

/**
 * REST controller for managing {@link com.xjgzinfo.usdp.domain.BladeVisual}.
 */
@RestController
@RequestMapping("/blade-visual")
public class VisualResource {

    private static final String ENTITY_NAME = "AvueServer4jAppBladeVisual";
    private final Logger log = LoggerFactory.getLogger(VisualResource.class);
    private final BladeVisualService bladeVisualService;
    private final BladeVisualQueryService bladeVisualQueryService;
    private final BladeVisualConfigService bladeVisualConfigService;
    private final BladeVisualConfigQueryService bladeVisualConfigQueryService;
    private final ImgAssetsService imgAssetsService;
    private final MinioClient minioClient;
    private final JwtDecoder jwtDecoder;
    @Value("${spring.application.name:usdp-app-unkown}")
    private String applicationName;
    @Value(value = "${minio.bucket:img}")
    private String bucket;
    @Value("${minio.host:http://localhost:9000}")
    private String miniHost;
    @Value("${minio.url:http://minio:9000}")
    private String miniUrl;

    public VisualResource(BladeVisualService bladeVisualService, BladeVisualQueryService bladeVisualQueryService, BladeVisualConfigService bladeVisualConfigService, BladeVisualConfigQueryService bladeVisualConfigQueryService, ImgAssetsService imgAssetsService, MinioClient minioClient, JwtDecoder jwtDecoder) {
        this.bladeVisualService = bladeVisualService;
        this.bladeVisualQueryService = bladeVisualQueryService;
        this.bladeVisualConfigService = bladeVisualConfigService;
        this.bladeVisualConfigQueryService = bladeVisualConfigQueryService;
        this.imgAssetsService = imgAssetsService;
        this.minioClient = minioClient;
        this.jwtDecoder = jwtDecoder;
    }

    /**
     * {@code POST  /visual/save} : 创建实体 bladeVisual.
     *
     * @param bladeVisualVO the bladeVisualDTO to create.
     * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new bladeVisualDTO, or with status {@code 400 (Bad Request)} if the bladeVisual has already an ID.
     * @throws URISyntaxException if the Location URI syntax is incorrect.
     */
    @PostMapping("/visual/save")
    public ResponseResult<BladeVisualDTO> createBladeVisual(@Valid @RequestBody BladeVisualVO bladeVisualVO) throws URISyntaxException {
        log.debug("REST request to save BladeVisual : {}", bladeVisualVO);
        if (bladeVisualVO.getVisual() != null && bladeVisualVO.getConfig() != null) {
            if (bladeVisualVO.getVisual().getId() != null || bladeVisualVO.getConfig().getId() != null) {
                return new ResponseResult(200, null, "ID已存在", false);
            }
            BladeVisualDTO bladeVisualDTO = bladeVisualVO.getVisual();
            bladeVisualDTO.setCreateTime(Instant.now());
            BladeVisualDTO result = bladeVisualService.save(bladeVisualDTO);
            if (result.getId() != null) {
                BladeVisualConfigDTO bladeVisualConfigDTO = bladeVisualVO.getConfig();
                bladeVisualConfigDTO.setVisualId(result.getId());
                bladeVisualConfigDTO.setComponent("[]");
                BladeVisualConfigDTO result1 = bladeVisualConfigService.save(bladeVisualConfigDTO);
                if (result1.getId() != null) {
                    return new ResponseResult(200, result, "创建成功", true);
                }
            }
        }
        return new ResponseResult(400, null, "创建失败", false);
    }


    /**
     * {@code POST  /visual/copy} : 拷贝实体 bladeVisual.
     *
     * @param id the bladeVisualDTO to create.
     * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new bladeVisualDTO, or with status {@code 400 (Bad Request)} if the bladeVisual has already an ID.
     */
    @PostMapping("/visual/copy")
    public ResponseResult<String> copyBladeVisual(@RequestParam Long id) {
        log.debug("REST request to copy BladeVisual : {}", id);
        Optional<BladeVisualDTO> optionalBladeVisualDTO = bladeVisualService.findOne(id);
        if (optionalBladeVisualDTO.isPresent()) {
            BladeVisualDTO bladeVisualDTO = optionalBladeVisualDTO.get();
            bladeVisualDTO.setId(null);
            bladeVisualDTO.setCreateTime(Instant.now());
            BladeVisualDTO result = bladeVisualService.save(bladeVisualDTO);
            if (result != null) {
                BladeVisualConfigCriteria criteria = new BladeVisualConfigCriteria();
                LongFilter idFilter = new LongFilter();
                idFilter.setEquals(id);
                criteria.setVisualId(idFilter);
                List<BladeVisualConfigDTO> bladeVisualConfigDTOS = bladeVisualConfigQueryService.findByCriteria(criteria);
                if (bladeVisualConfigDTOS.size() > 0) {
                    BladeVisualConfigDTO bladeVisualConfigDTO = bladeVisualConfigDTOS.get(0);
                    bladeVisualConfigDTO.setId(null);
                    bladeVisualConfigDTO.setVisualId(result.getId());
                    bladeVisualConfigService.save(bladeVisualConfigDTO);
                    return new ResponseResult(200, String.valueOf(result.getId()), "修改成功", true);
                }
            }
        }
        return new ResponseResult(200, "", "拷贝数据异常", false);
    }

    /**
     * {@code PUT  /visual/update} : 修改实体 bladeVisual.
     *
     * @param bladeVisualVO the bladeVisualVO to update.
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated bladeVisualDTO,
     * or with status {@code 400 (Bad Request)} if the bladeVisualDTO is not valid,
     * or with status {@code 500 (Internal Server Error)} if the bladeVisualDTO couldn't be updated.
     * @throws URISyntaxException if the Location URI syntax is incorrect.
     */
    @PostMapping("/visual/update")
    public ResponseResult<BladeVisualDTO> updateBladeVisual(@Valid @RequestBody BladeVisualVO bladeVisualVO) throws URISyntaxException {
        log.debug("REST request to update BladeVisual : {}", bladeVisualVO);
        if (bladeVisualVO.getVisual().getId() == null) {
            return new ResponseResult(200, null, "修改失败,id不能为空", false);
        }
        Optional<BladeVisualDTO> optionalBladeVisualDTO = bladeVisualService.findOne(bladeVisualVO.getVisual().getId());
        if (optionalBladeVisualDTO.isPresent()) {
            if (bladeVisualVO.getConfig() != null) {
                bladeVisualConfigService.save(bladeVisualVO.getConfig());
            }
            BladeVisualDTO bladeVisualDTO = optionalBladeVisualDTO.get();
            //查找空值
            String[] nullPropertyNames = BeanUtilsHepler.getNullPropertyNames(bladeVisualVO.getVisual());
            BeanUtil.copyProperties(bladeVisualVO.getVisual(), bladeVisualDTO, nullPropertyNames);
            bladeVisualDTO.setUpdateTime(Instant.now());
            BladeVisualDTO result = bladeVisualService.save(bladeVisualDTO);
            return new ResponseResult(200, result, "修改成功", true);
        } else {
            return new ResponseResult(200, null, "修改失败，未找到数据", false);
        }
    }

    /**
     * {@code GET  /visual/list} : 分页获取实体列表 bladeVisuals.
     *
     * @param pageable the pagination information.
     * @param criteria the criteria which the requested entities should match.
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of bladeVisuals in body.
     */
    @GetMapping("/visual/list")
    public ResponsePage<List<BladeVisualDTO>> getAllBladeVisuals(BladeVisualCriteria criteria, Pageable pageable) {
        log.debug("REST request to get BladeVisuals by criteria: {}", criteria);
        Page<BladeVisualDTO> page = bladeVisualQueryService.findByCriteria(criteria, pageable);
        PageWapper<BladeVisualDTO> pageWapper = new PageWapper(page.getNumber(), page.getTotalPages(), page.getContent(), page.getSize(), page.getTotalElements());
        return new ResponsePage(200, pageWapper, "", true);
    }

    /**
     * {@code GET  /visual/count} : count all the bladeVisuals.
     *
     * @param criteria the criteria which the requested entities should match.
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the count in body.
     */
    @GetMapping("/visual/count")
    public ResponseEntity<Long> countBladeVisuals(BladeVisualCriteria criteria) {
        log.debug("REST request to count BladeVisuals by criteria: {}", criteria);
        return ResponseEntity.ok().body(bladeVisualQueryService.countByCriteria(criteria));
    }

    /**
     * {@code GET  /visual/detail} : ID查询实体 bladeVisual.
     *
     * @param id the id of the bladeVisualDTO to retrieve.
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the bladeVisualDTO, or with status {@code 404 (Not Found)}.
     */
    @GetMapping("/visual/detail")
    public ResponseResult<BladeVisualVO> getBladeVisual(@RequestParam(value = "id", required = false) Long id, @RequestParam(value = "id.equals", required = false) Long equalsId) {
        long queryId = id != null ? id : equalsId;
        log.debug("REST request to get BladeVisual : {}", queryId);
        Optional<BladeVisualDTO> bladeVisualDTO = bladeVisualService.findOne(queryId);
        BladeVisualVO visualVO = new BladeVisualVO();
        if (bladeVisualDTO.isPresent()) {
            visualVO.setVisual(bladeVisualDTO.get());
        }
        BladeVisualConfigCriteria criteria = new BladeVisualConfigCriteria();
        LongFilter idFilter = new LongFilter();
        idFilter.setEquals(id);
        criteria.setVisualId(idFilter);
        List<BladeVisualConfigDTO> bladeVisualConfigDTOS = bladeVisualConfigQueryService.findByCriteria(criteria);
        if (!bladeVisualConfigDTOS.isEmpty()) {
            visualVO.setConfig(bladeVisualConfigDTOS.get(0));
        }
        return new ResponseResult(200, visualVO, "", true);
    }

    /**
     * {@code DELETE  /visual/remove} : ID删除实体 bladeVisual.
     *
     * @param id the id of the bladeVisualDTO to delete.
     * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
     */
    @PostMapping("/visual/remove")
    public ResponseResult<Void> deleteBladeVisual(@RequestParam(value = "id", required = false) Long id, @RequestParam(value = "id.equals", required = false) Long equalsId) {
        long deleteId = id != null ? id : equalsId;
        log.debug("REST request to delete BladeVisual : {} ", deleteId);
        bladeVisualService.delete(deleteId);
        BladeVisualConfigCriteria criteria = new BladeVisualConfigCriteria();
        LongFilter idFilter = new LongFilter();
        idFilter.setEquals(deleteId);
        criteria.setVisualId(idFilter);
        List<BladeVisualConfigDTO> bladeVisualConfigDTOS = bladeVisualConfigQueryService.findByCriteria(criteria);
        if (!bladeVisualConfigDTOS.isEmpty()) {
            bladeVisualConfigService.delete(bladeVisualConfigDTOS.get(0).getId());
        }
        return new ResponseResult(200, null, "删除成功", true);
    }

    /**
     * {@code POST  /visual/put-file} : 上传文件.
     *
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the map, or with status {@code 404 (Not Found)}.
     */
    @PostMapping(value = "/visual/put-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseResult<Map<String, String>> upload(HttpServletRequest request, @RequestParam("file") MultipartFile file,
                                                      @RequestParam(name = "type", required = false, defaultValue = "4") int type,
                                                      @RequestParam(name = "isPublic", required = false, defaultValue = "1") int isPublic) {
        Map<String, String> result = new HashMap<>();
        try (InputStream ins = file.getInputStream()) {
            // 获取文件输入流
            String fileName = file.getOriginalFilename() != null ? file.getOriginalFilename() : Instant.now().getEpochSecond() + ".jpg";

            PutObjectOptions putObjectOptions = new PutObjectOptions(file.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
            // 文件的ContentType
            putObjectOptions.setContentType(file.getContentType());
            minioClient.putObject(this.bucket, IMG_DIRS[type] + "/" + fileName, ins, putObjectOptions);
            String link = minioClient.getObjectUrl(this.bucket, IMG_DIRS[type] + "/" + fileName);
            if (link != null) {
                result.put("link", link.replace(miniHost, miniUrl));
                result.put("link", link);
            }
            result.put("name", fileName);
            // 上传素材写入图片资产库
            if (type != 4) {
                ImgAssetsDTO imgAssetsDTO = new ImgAssetsDTO();
                Optional<String> jwtOptions = SecurityUtils.getCurrentUserJWT();
                if (jwtOptions.isPresent()) {
                    Jwt jwt = jwtDecoder.decode(jwtOptions.get());
                    String userName = jwt.getClaims().get(AuthConstant.USERNAME_CLAIM).toString();
                    long userId = Long.valueOf(jwt.getClaims().get(AuthConstant.USERID_CLAIM).toString());
                    imgAssetsDTO.setCreateUser(userName);
                    imgAssetsDTO.setUserId(userId);
                }
                imgAssetsDTO.setUrl(result.get("link"));
                imgAssetsDTO.setName(fileName);
                imgAssetsDTO.setType(String.valueOf(type));
                imgAssetsDTO.setIsPublic(isPublic == 1 ? true : false);
                imgAssetsDTO.setCreateDate(Instant.now());
                imgAssetsService.save(imgAssetsDTO);
            }
            return new ResponseResult(200, result, "上传成功", true);
        } catch (Exception e) {
            return new ResponseResult(400, result, "上传失败", false);
        }
    }
}
